package cn.server.util;

import java.io.File;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateSessionFactory {

	/**
	 * Location of hibernate.cfg.xml file. Location should be on the classpath
	 * as Hibernate uses #resourceAsStream style lookup for its configuration
	 * file. The default classpath location of the hibernate config file is in
	 * the default package. Use #setConfigFile() to update the location of the
	 * configuration file for the current session.
	 */
	public static final String CONFIG_FILE_LOCATION = "config/hibernate.cfg.xml";

	private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();

	private static Configuration configuration;

	private static org.hibernate.SessionFactory sessionFactory;

	private final static Log logger = LogFactory
			.getLog(HibernateSessionFactory.class);

	private HibernateSessionFactory() {
	}

	/**
	 * Returns the ThreadLocal Session instance. Lazy initialize the
	 * <code>SessionFactory</code> if needed.
	 * 
	 * @return Session
	 * @throws HibernateException
	 */
	public static Session getSession() throws HibernateException {
		Session session = (Session) threadLocal.get();
		if (session == null || !session.isOpen()) {
			if (sessionFactory == null) {
				rebuildSessionFactory();
			}
			session = (sessionFactory != null) ? sessionFactory.openSession()
					: null;
			threadLocal.set(session);
		}
		return session;
	}

	/**
	 * Rebuild hibernate session factory
	 * 
	 */
	public static void rebuildSessionFactory() {
		try {
			// System.out.println(configFile);
			File f = new File(CONFIG_FILE_LOCATION);
			if (f.exists()) {
				configuration = new Configuration();
				configuration.configure(f);
				sessionFactory = configuration.buildSessionFactory();
				closeSession();
			} else {
				System.err.println("%%%% " + CONFIG_FILE_LOCATION
						+ " not found %%%%");
			}
		} catch (Exception e) {
			System.err.println("%%%% Error Creating SessionFactory %%%%");
			e.printStackTrace();
		}
	}

	/**
	 * Close the single hibernate session instance.
	 * 
	 * @throws HibernateException
	 */
	public static void closeSession() {
		try {
			Session session = (Session) threadLocal.get();
			threadLocal.set(null);
			if (session != null) {
				session.close();
			}
		} catch (Throwable e) {
			logger.error("session close error!", e);
		}
	}

	public static void commitSession(Session session) throws Throwable {
		if (session != null) {
			try {
				session.getTransaction().commit();
			} catch (Throwable e) {
				logger.error("commit error", e);
				try {
					session.getTransaction().rollback();
				} catch (Throwable t) {
					logger.error("rollback error", t);
				}
				throw e;
			}
		}
	}

	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public static Configuration getConfiguration() {
		return configuration;
	}
}